﻿using System;

namespace Laugh.Data
{
    public interface IEntity
    {
    }

    public interface IEntity<TId> : IEntity
    {
        TId Id { get; }
        bool IsTransient();
    }

    public abstract class Entity<TId> : IEntity<TId>
    {
        int? _requestedHashCode;
        TId _id = default(TId);

        public virtual TId Id
        {
            get { return _id; }
            set
            {
                _id = value;
                OnIdChanged();
            }
        }

        public virtual bool IsTransient()
        {
            return Id == null ? true : Id.Equals(default(TId));
        }

        protected virtual void OnIdChanged()
        {

        }

        #region 重写
        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Entity<TId>))
                return false;

            if (Object.ReferenceEquals(this, obj))
                return true;

            Entity<TId> item = (Entity<TId>)obj;

            if (item.IsTransient() || this.IsTransient())
                return false;
            else
                return item.Id.Equals(this.Id);
        }

        public override int GetHashCode()
        {
            if (!IsTransient())
            {
                if (!_requestedHashCode.HasValue)
                    _requestedHashCode = this.Id.GetHashCode() ^ 31;

                return _requestedHashCode.Value;
            }
            else
                return base.GetHashCode();

        }

        public static bool operator ==(Entity<TId> left, Entity<TId> right)
        {
            if (Object.Equals(left, null))
                return (Object.Equals(right, null)) ? true : false;
            else
                return left.Equals(right);
        }

        public static bool operator !=(Entity<TId> left, Entity<TId> right)
        {
            return !(left == right);
        }
        #endregion
    }
}
